/**
Author: Maciej Oczko
Date: November 2011
*/

#ifndef POOLMEMORYMANAGER_H_
#define POOLMEMORYMANAGER_H_
#include <cassert>

class PoolMemoryManager 
{
private:
	/// Array of objects.
	char *m_Data;
	/// Array of pointers to free elements.
	char **m_FreeObjects;
	/// Array of ids to pointers.
	char **m_Pointers;
	/// First available object.
	unsigned m_FreeCount;
	/// Number of objects in allocated memory.
	unsigned m_Capacity;
	/// Size of single object
	unsigned m_ElementSize;

	/// Disable copying.
	PoolMemoryManager(const PoolMemoryManager &);
	PoolMemoryManager & operator=(const PoolMemoryManager &);
public:
	PoolMemoryManager(unsigned p_ElementSize, unsigned p_Capacity);
	~PoolMemoryManager();
	/// Makes all instances available for allocation.
	void FreeAll();
	/// Returns new instance of memory element.
	void * New();
	/// Returns new instance of memory element and id.
	void * New(unsigned &p_id);
	/// Reclaims the instance referenced by p_Instance.
	void Delete(void *p_Instance);
	// Reclaims the instance referenced by p_Id.
	bool Delete(unsigned p_Id);

	/// Returns used objects count.
	inline unsigned GetUsedCount() const { return m_Capacity - m_FreeCount; }
	/// Returns free objects count.
	inline unsigned GetFreeCount() const { return m_FreeCount; }

	/// Returns the capacity of memory block.
	inline unsigned GetCapacity() const {  return m_Capacity; }
	/// Return object size.
	inline unsigned GetElementSize() const { return m_ElementSize; }

	/// Returns size of used objects count.
	inline unsigned GetUsedSize() const { return GetUsedCount() * m_ElementSize; }
	/// Returns size of free objects count.
	inline unsigned GetFreeSize() const { return GetFreeCount() * m_ElementSize; }
	/// Returns the size of allocated memory block.
	inline unsigned GetAllSize() const { return m_Capacity * m_ElementSize; }

	/// Returns true if memory block is free.
	inline bool IsEmpty() const { return m_FreeCount == m_Capacity; }
	/// Returns true if memory block is full.
	inline bool IsFull() const { return m_FreeCount == 0; }
	/// Returns true if given address belongs to this memory block.
	inline bool BelongsTo(void *ptr) const { return (ptr >= m_Data) && (ptr < m_Data + m_Capacity * m_ElementSize ); }
};


#endif
